#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "mqtt_client.h"
#include "simple_wifi_sta.h"
#include "dht22_sensor.h"  // 引入DHT22头文件

// 日志标签（独立于DHT22的标签）
static const char* MAIN_TAG = "main";

// MQTT配置
#define MQTT_ADDRESS    "mqtt://117.159.17.24"
#define MQTT_PORT       1883
#define MQTT_CLIENT     "esp32c6_dht22_client"  // 唯一客户端ID
#define MQTT_USERNAME   "root"
#define MQTT_PASSWORD   "123456"
#define MQTT_PUBLIC_TOPIC      "/89/esp32c6_dht22_client/property/post"    // 发布温湿度的主题
#define MQTT_SUBSCRIBE_TOPIC    "/89/esp32c6_dht22_client/function/get"   // 订阅的主题

// WiFi事件标志
#define WIFI_CONNECT_BIT     BIT0
static EventGroupHandle_t   s_wifi_ev = NULL;

// MQTT客户端句柄及连接状态
static esp_mqtt_client_handle_t     s_mqtt_client = NULL;
static bool   s_is_mqtt_connected = false;

// 温湿度全局变量（供DHT22任务和MQTT发布使用）
float g_humidity = 0.0f;
float g_temperature = 0.0f;
bool g_is_dht_valid = false;


/**
 * MQTT发布温湿度数据函数
 */
void mqtt_publish_dht_data(esp_mqtt_client_handle_t client) {
    if (!s_is_mqtt_connected || !g_is_dht_valid) {
        return;  // MQTT未连接或数据无效时不发布
    }

    char payload[64];
    snprintf(payload, sizeof(payload), 
             "{\"humidity\":%.1f,\"temperature\":%.1f}", 
             g_humidity, g_temperature);
    
    // 发布消息到指定主题
    esp_mqtt_client_publish(client,
                            MQTT_PUBLIC_TOPIC,
                            payload,
                            strlen(payload),
                            1,  // QoS=1
                            0); // 不保留消息
}


/**
 * MQTT事件处理函数
 */
static void mqtt_event_handler(void* event_handler_arg,
                               esp_event_base_t event_base,
                               int32_t event_id,
                               void* event_data) {
    esp_mqtt_event_handle_t event = event_data;
    esp_mqtt_client_handle_t client = event->client;

    switch ((esp_mqtt_event_id_t)event_id) {
        case MQTT_EVENT_CONNECTED:
            ESP_LOGI(MAIN_TAG, "MQTT连接成功");
            s_is_mqtt_connected = true;
            // 订阅主题
            esp_mqtt_client_subscribe_single(client, MQTT_SUBSCRIBE_TOPIC, 1);
            // 连接成功后立即发布一次温湿度（如果已读取到）
            if (g_is_dht_valid) {
                mqtt_publish_dht_data(client);
            }
            break;

        case MQTT_EVENT_DISCONNECTED:
            ESP_LOGI(MAIN_TAG, "MQTT连接断开，尝试重连...");
            s_is_mqtt_connected = false;
            esp_mqtt_client_start(client);  // 自动重连
            break;

        case MQTT_EVENT_SUBSCRIBED:
            ESP_LOGI(MAIN_TAG, "订阅主题成功, msg_id=%d", event->msg_id);
            break;

        case MQTT_EVENT_DATA:
            ESP_LOGI(MAIN_TAG, "收到消息:");
            ESP_LOGI(MAIN_TAG, "主题=%.*s", event->topic_len, event->topic);
            ESP_LOGI(MAIN_TAG, "内容=%.*s", event->data_len, event->data);
            break;

        case MQTT_EVENT_ERROR:
            ESP_LOGE(MAIN_TAG, "MQTT错误, 错误类型=%d", event->error_handle->error_type);
            break;

        default:
            break;
    }
}


/**
 * 启动MQTT客户端
 */
void mqtt_start(void) {
    esp_mqtt_client_config_t mqtt_cfg = {
        .broker = {
            .address = {
                .uri = MQTT_ADDRESS,
                .port = MQTT_PORT
            }
        },
        .credentials = {
            .client_id = MQTT_CLIENT,
            .username = MQTT_USERNAME,
            .authentication = {
                .password = MQTT_PASSWORD
            }
        }
    };

    s_mqtt_client = esp_mqtt_client_init(&mqtt_cfg);
    esp_mqtt_client_register_event(s_mqtt_client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
    esp_mqtt_client_start(s_mqtt_client);
}


/**
 * WiFi事件回调（通知连接状态）
 */
void wifi_event_handler(WIFI_EV_e ev) {
    if (ev == WIFI_CONNECTED) {
        xEventGroupSetBits(s_wifi_ev, WIFI_CONNECT_BIT);
        ESP_LOGI(MAIN_TAG, "WiFi连接成功");
    }
}


/**
 * DHT22温湿度读取任务（仅在main.c中定义一次）
 */
void dht22_task(void *pvParameters) {
    vTaskDelay(pdMS_TO_TICKS(2000));  // 上电后等待传感器稳定
    ESP_LOGI(DHT22_TAG, "DHT22任务启动");

    float humidity, temperature;
    while (1) {
        // 读取温湿度
        if (dht22_read(&humidity, &temperature)) {
            // 更新全局变量
            g_humidity = humidity;
            g_temperature = temperature;
            g_is_dht_valid = true;
            ESP_LOGI(DHT22_TAG, "读取成功: 湿度=%.1f%%RH, 温度=%.1f℃", humidity, temperature);

            // 如果MQTT已连接，立即发布
            if (s_is_mqtt_connected) {
                mqtt_publish_dht_data(s_mqtt_client);
            }
        } else {
            g_is_dht_valid = false;
            ESP_LOGE(DHT22_TAG, "读取失败");
        }

        vTaskDelay(pdMS_TO_TICKS(2000));  // 每2秒读取一次
    }
}


/**
 * 主函数（仅在main.c中定义一次）
 */
void app_main(void) {
    // 1. 初始化NVS
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ESP_ERROR_CHECK(nvs_flash_init());
    }

    // 2. 创建WiFi事件组
    s_wifi_ev = xEventGroupCreate();

    // 3. 初始化DHT22引脚（上拉模式）
    gpio_reset_pin(DHT22_PIN);
    gpio_set_pull_mode(DHT22_PIN, GPIO_PULLUP_ONLY);

    // 4. 初始化WiFi并等待连接
    wifi_sta_init(wifi_event_handler);
    EventBits_t ev = xEventGroupWaitBits(
        s_wifi_ev,
        WIFI_CONNECT_BIT,
        pdTRUE,
        pdFALSE,
        portMAX_DELAY
    );

    // 5. WiFi连接成功后启动MQTT
    if (ev & WIFI_CONNECT_BIT) {
        mqtt_start();
    } else {
        ESP_LOGE(MAIN_TAG, "WiFi连接超时，程序退出");
        vTaskDelete(NULL);
        return;
    }

    // 6. 创建DHT22读取任务
    xTaskCreate(
        dht22_task,       // 任务函数
        "dht22_task",     // 任务名称
        2048,             // 栈大小
        NULL,             // 任务参数
        5,                // 优先级
        NULL              // 任务句柄（不保存）
    );

    // 7. 主循环（空循环，仅保持任务运行）
    while (1) {
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}